/**
 * 广寒宫
 * 网址:www.guanghangong.xyz
 */
package com.moon.admin.framework.secure.aop;

import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.moon.admin.framework.MoonConstants;
import com.moon.admin.framework.MoonConstants.RequestFormEnum;
import com.moon.admin.framework.secure.AuthUtils;
import com.moon.admin.framework.springmvc.domain.RCode;
import com.moon.admin.framework.util.MoonException;
import com.moon.admin.framework.util.ToolUtils;

/**
 * 解决表单重复提交
 * @author ninglong
 */
@Aspect
@Slf4j
public class FormRepeatSubmitAspect {
	
	private static final Cache<String, String> caches = CacheBuilder.newBuilder()
            // 最大缓存 100 个
            .maximumSize(1000)
            // 设置写缓存后 5 秒钟过期
            .expireAfterWrite(5, TimeUnit.SECONDS)
            .build();
	/**
	 * 切 方法 和 类上的 @FormRepeat 注解
	 */
	@Around(
		"@annotation(com.moon.admin.framework.secure.annotation.FormRepeat) || " +
			"@within(com.moon.admin.framework.secure.annotation.FormRepeat)"
	)
	public Object formRepeatSubmit(ProceedingJoinPoint point) throws Throwable {
		String requestFrom = ToolUtils.getRequest().getHeader(MoonConstants.REQUEST_FROM);
		String token = AuthUtils.getToken();
		if (token == null || ToolUtils.isEmpty(requestFrom) || RequestFormEnum.feign.name().equals(requestFrom)) {
			return point.proceed();
		}
		String key = token+":"+ToolUtils.getRequest().getRequestURI();//TODO 要保证同一个人的唯一性
        if(caches.getIfPresent(key)==null){
        	caches.put(key, token);
        }else {
        	log.error(RCode.FORM_REPEAT_SUBMIT.getMsg());
            throw new MoonException(RCode.FORM_REPEAT_SUBMIT.getCode(),RCode.FORM_REPEAT_SUBMIT.getMsg());
        }
        try{
        	return point.proceed();
        }finally{
        	caches.invalidate(key);
        }
	}
}